<template>
  <div class="add-wrapper">
    <div class="points">
      <span class="prefix-title">巡检点</span>
      <el-button type="primary" @click="choosePoints">选择巡检点</el-button>

      <el-table class="custom-table" :data="tableData">
        <el-table-column type="index" label="序号" width="60px" />
        <el-table-column prop="code" label="巡检点编号" />
        <el-table-column prop="name" label="巡检点名称" />
        <el-table-column prop="type" label="巡检点类型" />
        <el-table-column label="地理位置">
          <template #default="scope">
            <el-row align="middle">
              <span>{{ scope.row.address }}</span>
              <SvgIcon name="location1" size="14px" />
            </el-row>
          </template>
        </el-table-column>
        <el-table-column prop="park" label="所属园区" />
        <el-table-column label="操作" width="80px">
          <template #default="scope">
            <el-button link type="danger" @click="handleDelete(scope.row)"
              >删除</el-button
            >
          </template>
        </el-table-column>
      </el-table>
    </div>

    <div class="route">
      <span class="prefix-title">路线编辑（注意：请先选择巡检点）</span>
      <el-row align="middle">
        <el-popconfirm title="是否重绘巡检路线" width="160" @confirm="reDraw">
          <template #reference>
            <el-button :disabled="!checkPoints.length" type="primary"
              >重绘</el-button
            >
          </template>
        </el-popconfirm>
        <span class="description">请依次点击巡检点以确定巡检顺序</span>
      </el-row>
      <MapboxMap
        :map-id="mapId"
        @after-map-loaded="afterMapLoaded"
        @before-map-destroyed="beforeMapDestroyed"
      />
    </div>

    <InspectionPointDialog v-model:visible="pointDialogVisible" />
  </div>
</template>

<script setup>
import { ElMessageBox } from 'element-plus'
import mapboxgl from 'mapbox-gl'
import { nanoid } from 'nanoid'
import { computed, onMounted, ref, shallowRef } from 'vue'
import { useRouteQuery } from '@vueuse/router'
import MapboxMap from '@/components/mapbox-map.vue'
import InspectionPointDialog from './components/InspectionPointDialog.vue'

let _map

const mapId = nanoid()

const id = useRouteQuery('id')

const pointDialogVisible = ref(false)

const tableData = ref([])

// 巡检点列表
const checkPoints = ref([
  {
    name: '考勤点1',
    location: [106.523299, 29.7984],
    address: '7栋负一层东南处1号点位',
  },
  {
    name: '考勤点2',
    location: [106.535618, 29.801968],
    address: '7栋负一层东南处2号点位7栋负一层东南处2号点位',
  },
  {
    name: '考勤点3',
    location: [106.527286, 29.791165],
    address: '7栋负一层东南处3号点位',
  },
])

// 巡检点popup列表
const checkPointPopupList = shallowRef([])

const getTableData = () => {
  for (let i = 0; i < 10; i++) {
    tableData.value.push({
      pkid: i.toString(),
      code: 'aaaaa',
      name: '巡检点' + i,
      type: '消防设施类',
      address: '1栋负1层东南处1号点位',
      park: '园区一',
    })
  }
}

const choosePoints = () => {
  pointDialogVisible.value = true
}

const handleDelete = (row) => {
  ElMessageBox.confirm('是否确定删除该项？', '提示', {
    confirmButtonText: '确定',
    cancelButtonText: '取消',
    type: 'warning',
  })
    .then(() => {
      console.log('delete:', row.pkid)
    })
    .catch(() => {
      console.log('取消删除')
    })
}

// 重绘
const reDraw = () => {
  removeRoutesLayer()
  checkPointPopupList.value.forEach((popup) => {
    popup.remove()
  })
  checkPoints.value = []
  checkPointPopupList.value = []
}

const afterMapLoaded = (id, map) => {
  console.log('afterMapLoaded:', id, map)
  _map = map

  if (checkPoints.value.length > 1) {
    addRoutesLayer(generateRoutesGeojson(checkPoints.value), true)
  }
  if (checkPoints.value.length) {
    addPoint(checkPoints.value)
  }

  _map.doubleClickZoom.disable()
  _map.on('click', onMapClick)
}

const beforeMapDestroyed = (id, map) => {
  console.log('beforeMapDestroyed:', id, map)
  _map.off('click', onMapClick)
}

const onMapClick = (e) => {
  console.log('map click:', e)
}

/**
 * 生成轨迹线geojson
 *
 * @param {Array} points 轨迹点数组
 */
const generateRoutesGeojson = (points) => {
  return {
    type: 'FeatureCollection',
    features: [
      {
        type: 'Feature',
        properties: {},
        geometry: {
          coordinates: points.map((point) => point.location),
          type: 'LineString',
        },
      },
    ],
  }
}

/**
 * 添加轨迹线图层
 *
 * @param {Object} geojson 轨迹线geojson
 *
 * @param {Boolean} fitBounds 是否自动定位
 */
const addRoutesLayer = (geojson, fitBounds) => {
  removeRoutesLayer()
  _map.addSource('routes', {
    type: 'geojson',
    data: geojson,
  })
  _map.addLayer({
    type: 'line',
    source: 'routes',
    id: 'routes',
    paint: {
      'line-color': '#666666',
      'line-width': 3,
    },
  })

  if (fitBounds) {
    const coordinates = geojson.features[0].geometry.coordinates
    const bounds = new mapboxgl.LngLatBounds(coordinates[0], coordinates[0])
    for (const coord of coordinates) {
      bounds.extend(coord)
    }
    _map.fitBounds(bounds, {
      padding: 60,
    })
  }
}

const removeRoutesLayer = () => {
  if (_map.getLayer('routes')) {
    _map.removeLayer('routes')
  }
  if (_map.getSource('routes')) {
    _map.removeSource('routes')
  }
}

/**
 * 添加轨迹点
 *
 * @param {Array} points 轨迹点数组
 */
const addPoint = (points) => {
  points.forEach((point, index) => {
    const popup = new mapboxgl.Popup({
      anchor: 'bottom',
      className: 'check-point-popup',
      closeButton: false,
      closeOnClick: false,
      focusAfterOpen: false,
      offset: [0, 10],
    })
      .setLngLat(point.location)
      .setHTML(generatePointHTML(index, point.name, point.status))
      .addTo(_map)
    checkPointPopupList.value.push(popup)
  })
}

const generatePointHTML = (index, name, status) => {
  let statusClass = 'normal'
  if (status === 0) {
    statusClass = 'exception'
  }
  return `
  <div class="check-point-content ${statusClass}">
    <div class="check-point-name">
      <span>巡检点：${name}</span>
    </div>

    <div class="check-point-index">
      <span>${index + 1}</span>
    </div>
  </div>
  `
}

onMounted(() => {
  if (isEdit.value) {
    getTableData()
  }
})

const isEdit = computed(() => !!id.value)
</script>

<style lang="scss" scoped src="@/assets/styles/table.scss"></style>
<style lang="scss" scoped>
.add-wrapper {
  width: 100%;
  height: 100%;
  padding: 20px 0 20px 20px;
  border-radius: 4px;
  display: flex;
  flex-direction: column;
  background: #ffffff;
  box-shadow: 0px 0px 10px 0px rgba(72, 121, 238, 0.1);
  overflow-y: auto;

  .prefix-title {
    font-size: 16px;
    font-family: Source Han Sans CN;
    font-weight: 700;
    color: #151515;
    margin-left: -10px;
    margin-bottom: 20px;
    margin-right: 20px;
    position: relative;
    padding-left: 10px;

    &::before {
      content: ' ';
      position: absolute;
      left: 0;
      top: 0;
      width: 4px;
      height: 16px;
      background: linear-gradient(0deg, #4575ee 0%, #6297f5 100%);
      border-radius: 2px;
    }
  }

  & > div {
    padding-right: 20px;
    display: flex;
    flex-direction: column;

    & > .el-button {
      width: fit-content;
    }
  }

  .points {
    .el-table {
      max-height: 320px;
      margin-top: 20px;
    }
  }

  .route {
    flex: 1;
    min-height: 500px;
    margin-top: 20px;

    .description {
      margin-left: 10px;
      color: #757575;
      font-size: 14px;
      font-weight: 600;
    }

    .mapbox-map {
      flex: 1;
      margin-top: 20px;
    }
  }
}
</style>
